<html lang="en">

<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>JDK中应用的设计模式 - bravo</title>
<link rel="shortcut icon" href="https://JoyZgq.github.io/favicon.ico">
<link href="https://cdn.jsdelivr.net/npm/remixicon@2.2.0/fonts/remixicon.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/animate.css@3.7.2/animate.min.css">
<link rel="stylesheet" href="https://JoyZgq.github.io/media/css/tailwind.css">
<link rel="stylesheet" href="https://JoyZgq.github.io/styles/main.css">
<link rel="alternate" type="application/atom+xml" title="JDK中应用的设计模式 - bravo - Atom Feed" href="https://JoyZgq.github.io/atom.xml">


  <script async src="https://www.googletagmanager.com/gtag/js?id=UA-164181119-1"></script>
  <script>
    window.dataLayer = window.dataLayer || [];
    function gtag(){dataLayer.push(arguments);}
    gtag('js', new Date());
  
    gtag('config', 'UA-164181119-1');
  </script>
    

  <meta name="description" content="
摘自StackOverflow论坛回复,译文在下方

Creational patterns
Abstract factory (recognizeable by creational methods returning the fact..." />
  <meta property="og:title" content="JDK中应用的设计模式 - bravo">
  <meta property="og:description" content="
摘自StackOverflow论坛回复,译文在下方

Creational patterns
Abstract factory (recognizeable by creational methods returning the fact..." />
  <meta property="og:type" content="articles">
  <meta property="og:url" content="https://JoyZgq.github.io/post/vh9lsAukM/" />
  <meta property="og:image" content="https://JoyZgq.github.io/post-images/vh9lsAukM.webp">
  <meta property="og:image:height" content="630">
  <meta property="og:image:width" content="1200">
  <meta name="twitter:title" content="JDK中应用的设计模式 - bravo">
  <meta name="twitter:description" content="
摘自StackOverflow论坛回复,译文在下方

Creational patterns
Abstract factory (recognizeable by creational methods returning the fact...">
  <meta name="twitter:card" content="summary_large_image">
  <link rel="canonical" href="https://JoyZgq.github.io/post/vh9lsAukM/">

  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/photoswipe.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/default-skin/default-skin.css">
 
  
    <link rel="stylesheet" href="https://JoyZgq.github.io/media/css/prism-github.css">
  

  
</head>

<body>
  <div class="antialiased flex flex-col min-h-screen" id="app">
    <a href="https://JoyZgq.github.io" class="fixed top-0 left-0 mt-4 bg-black text-white dark:text-gray-700 dark:bg-yellow-50 dark:hover:bg-black dark:hover:text-white inline-flex p-2 pl-8 hover:text-gray-700 hover:bg-yellow-50 font-bold z-10 transition-fast animated fadeInLeft">
      bravo
    </a>
    <div class="max-w-4xl w-full mx-auto">
      <div class="shadow-box bg-white dark:bg-gray-600 rounded-lg pt-32 md:pt-64 px-4 md:px-8 pb-8 animated fadeIn mb-8">
        <h1 class="text-5xl font-semibold leading-normal pb-8 mb-8 border-b-8 border-gray-700">
          JDK中应用的设计模式
        </h1>
        
          <img src="https://JoyZgq.github.io/post-images/vh9lsAukM.webp" alt="JDK中应用的设计模式" class="block w-full mb-8">
        
        <div class="mb-8 flex flex-wrap">
          <div class="text-gray-400 text-sm mr-4">2020-04-22 · 14 min read</div>
          
        </div>
        <div class="markdown mb-8" v-pre>
          <blockquote>
<p>摘自StackOverflow论坛回复,译文在下方</p>
</blockquote>
<h2 id="creational-patterns"><a href="http://en.wikipedia.org/wiki/Creational_pattern">Creational patterns</a></h2>
<h3 id="abstract-factory"><a href="http://en.wikipedia.org/wiki/Abstract_factory_pattern">Abstract factory</a> (recognizeable by creational methods returning the factory itself which in turn can be used to create another abstract/interface type)</h3>
<ul>
<li><a href="http://docs.oracle.com/javase/8/docs/api/javax/xml/parsers/DocumentBuilderFactory.html#newInstance--"><code>javax.xml.parsers.DocumentBuilderFactory#newInstance()</code></a></li>
<li><a href="http://docs.oracle.com/javase/8/docs/api/javax/xml/transform/TransformerFactory.html#newInstance--"><code>javax.xml.transform.TransformerFactory#newInstance()</code></a></li>
<li><a href="http://docs.oracle.com/javase/8/docs/api/javax/xml/xpath/XPathFactory.html#newInstance--"><code>javax.xml.xpath.XPathFactory#newInstance()</code></a></li>
</ul>
<h3 id="builder"><a href="http://en.wikipedia.org/wiki/Builder_pattern">Builder</a> (recognizeable by creational methods returning the instance itself)</h3>
<ul>
<li><a href="http://docs.oracle.com/javase/8/docs/api/java/lang/StringBuilder.html#append-boolean-"><code>java.lang.StringBuilder#append()</code></a> (unsynchronized)</li>
<li><a href="http://docs.oracle.com/javase/8/docs/api/java/lang/StringBuffer.html#append-boolean-"><code>java.lang.StringBuffer#append()</code></a> (synchronized)</li>
<li><a href="http://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html#put-byte-"><code>java.nio.ByteBuffer#put()</code></a> (also on <a href="http://docs.oracle.com/javase/8/docs/api/java/nio/CharBuffer.html#put-char-"><code>CharBuffer</code></a>, <a href="http://docs.oracle.com/javase/8/docs/api/java/nio/ShortBuffer.html#put-short-"><code>ShortBuffer</code></a>, <a href="http://docs.oracle.com/javase/8/docs/api/java/nio/IntBuffer.html#put-int-"><code>IntBuffer</code></a>, <a href="http://docs.oracle.com/javase/8/docs/api/java/nio/LongBuffer.html#put-long-"><code>LongBuffer</code></a>, <a href="http://docs.oracle.com/javase/8/docs/api/java/nio/FloatBuffer.html#put-float-"><code>FloatBuffer</code></a> and <a href="http://docs.oracle.com/javase/8/docs/api/java/nio/DoubleBuffer.html#put-double-"><code>DoubleBuffer</code></a>)</li>
<li><a href="http://docs.oracle.com/javase/8/docs/api/javax/swing/GroupLayout.Group.html#addComponent-java.awt.Component-"><code>javax.swing.GroupLayout.Group#addComponent()</code></a></li>
<li>All implementations of <a href="http://docs.oracle.com/javase/8/docs/api/java/lang/Appendable.html"><code>java.lang.Appendable</code></a></li>
<li><a href="https://docs.oracle.com/javase/9/docs/api/java/util/stream/Stream.Builder.html"><code>java.util.stream.Stream.Builder</code></a></li>
</ul>
<h3 id="factory-method"><a href="http://en.wikipedia.org/wiki/Factory_method_pattern">Factory method</a> (recognizeable by creational methods returning an implementation of an abstract/interface type)</h3>
<ul>
<li><a href="http://docs.oracle.com/javase/8/docs/api/java/util/Calendar.html#getInstance--"><code>java.util.Calendar#getInstance()</code></a></li>
<li><a href="http://docs.oracle.com/javase/8/docs/api/java/util/ResourceBundle.html#getBundle-java.lang.String-"><code>java.util.ResourceBundle#getBundle()</code></a></li>
<li><a href="http://docs.oracle.com/javase/8/docs/api/java/text/NumberFormat.html#getInstance--"><code>java.text.NumberFormat#getInstance()</code></a></li>
<li><a href="http://docs.oracle.com/javase/8/docs/api/java/nio/charset/Charset.html#forName-java.lang.String-"><code>java.nio.charset.Charset#forName()</code></a></li>
<li><a href="http://docs.oracle.com/javase/8/docs/api/java/net/URLStreamHandlerFactory.html"><code>java.net.URLStreamHandlerFactory#createURLStreamHandler(String)</code></a> (Returns singleton object per protocol)</li>
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/util/EnumSet.html#of(E)"><code>java.util.EnumSet#of()</code></a></li>
<li><a href="https://docs.oracle.com/javase/8/docs/api/javax/xml/bind/JAXBContext.html#createMarshaller--"><code>javax.xml.bind.JAXBContext#createMarshaller()</code></a> and other similar methods</li>
</ul>
<h3 id="prototype"><a href="http://en.wikipedia.org/wiki/Prototype_pattern">Prototype</a> (recognizeable by creational methods returning a <em>different</em> instance of itself with the same properties)</h3>
<ul>
<li><a href="http://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#clone--"><code>java.lang.Object#clone()</code></a> (the class has to implement <a href="http://docs.oracle.com/javase/8/docs/api/java/lang/Cloneable.html"><code>java.lang.Cloneable</code></a>)</li>
</ul>
<h3 id="singleton"><a href="http://en.wikipedia.org/wiki/Singleton_pattern">Singleton</a> (recognizeable by creational methods returning the <em>same</em> instance (usually of itself) everytime)</h3>
<ul>
<li><a href="http://docs.oracle.com/javase/8/docs/api/java/lang/Runtime.html#getRuntime--"><code>java.lang.Runtime#getRuntime()</code></a></li>
<li><a href="http://docs.oracle.com/javase/8/docs/api/java/awt/Desktop.html#getDesktop--"><code>java.awt.Desktop#getDesktop()</code></a></li>
<li><a href="http://docs.oracle.com/javase/8/docs/api/java/lang/System.html#getSecurityManager--"><code>java.lang.System#getSecurityManager()</code></a></li>
</ul>
<h2 id="structural-patterns"><a href="http://en.wikipedia.org/wiki/Structural_pattern">Structural patterns</a></h2>
<h3 id="adapter"><a href="http://en.wikipedia.org/wiki/Adapter_pattern">Adapter</a> (recognizeable by creational methods taking an instance of <em>different</em> abstract/interface type and returning an implementation of own/another abstract/interface type which <em>decorates/overrides</em> the given instance)</h3>
<ul>
<li><a href="http://docs.oracle.com/javase/8/docs/api/java/util/Arrays.html#asList-T...-"><code>java.util.Arrays#asList()</code></a></li>
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#list-java.util.Enumeration-"><code>java.util.Collections#list()</code></a></li>
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#enumeration-java.util.Collection-"><code>java.util.Collections#enumeration()</code></a></li>
<li><a href="http://docs.oracle.com/javase/8/docs/api/java/io/InputStreamReader.html#InputStreamReader-java.io.InputStream-"><code>java.io.InputStreamReader(InputStream)</code></a> (returns a <code>Reader</code>)</li>
<li><a href="http://docs.oracle.com/javase/8/docs/api/java/io/OutputStreamWriter.html#OutputStreamWriter-java.io.OutputStream-"><code>java.io.OutputStreamWriter(OutputStream)</code></a> (returns a <code>Writer</code>)</li>
<li><a href="http://docs.oracle.com/javase/8/docs/api/javax/xml/bind/annotation/adapters/XmlAdapter.html#marshal-BoundType-"><code>javax.xml.bind.annotation.adapters.XmlAdapter#marshal()</code></a> and <a href="http://docs.oracle.com/javase/8/docs/api/javax/xml/bind/annotation/adapters/XmlAdapter.html#unmarshal-ValueType-"><code>#unmarshal()</code></a></li>
</ul>
<h3 id="bridge"><a href="http://en.wikipedia.org/wiki/Bridge_pattern">Bridge</a> (recognizeable by creational methods taking an instance of <em>different</em> abstract/interface type and returning an implementation of own abstract/interface type which <em>delegates/uses</em> the given instance)</h3>
<ul>
<li>None comes to mind yet. A fictive example would be <code>new LinkedHashMap(LinkedHashSet, List)</code> which returns an unmodifiable linked map which doesn't clone the items, but <em>uses</em> them. The <a href="http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#newSetFromMap-java.util.Map-"><code>java.util.Collections#newSetFromMap()</code></a> and <a href="http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#singleton-T-"><code>singletonXXX()</code></a> methods however comes close.</li>
</ul>
<h3 id="composite"><a href="http://en.wikipedia.org/wiki/Composite_pattern">Composite</a> (recognizeable by behavioral methods taking an instance of <em>same</em> abstract/interface type into a tree structure)</h3>
<ul>
<li><a href="http://docs.oracle.com/javase/8/docs/api/java/awt/Container.html#add-java.awt.Component-"><code>java.awt.Container#add(Component)</code></a> (practically all over Swing thus)</li>
<li><a href="http://docs.oracle.com/javaee/7/api/javax/faces/component/UIComponent.html#getChildren--"><code>javax.faces.component.UIComponent#getChildren()</code></a> (practically all over JSF UI thus)</li>
</ul>
<h3 id="decorator"><a href="http://en.wikipedia.org/wiki/Decorator_pattern">Decorator</a> (recognizeable by creational methods taking an instance of <em>same</em> abstract/interface type which adds additional behaviour)</h3>
<ul>
<li>All subclasses of <a href="http://docs.oracle.com/javase/8/docs/api/java/io/InputStream.html"><code>java.io.InputStream</code></a>, <a href="http://docs.oracle.com/javase/8/docs/api/java/io/OutputStream.html"><code>OutputStream</code></a>, <a href="http://docs.oracle.com/javase/8/docs/api/java/io/Reader.html"><code>Reader</code></a> and <a href="http://docs.oracle.com/javase/8/docs/api/java/io/Writer.html"><code>Writer</code></a> have a constructor taking an instance of same type.</li>
<li><a href="http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html"><code>java.util.Collections</code></a>, the <a href="http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#checkedCollection-java.util.Collection-java.lang.Class-"><code>checkedXXX()</code></a>, <a href="http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#synchronizedCollection-java.util.Collection-"><code>synchronizedXXX()</code></a> and <a href="http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#unmodifiableCollection-java.util.Collection-"><code>unmodifiableXXX()</code></a> methods.</li>
<li><a href="http://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpServletRequestWrapper.html"><code>javax.servlet.http.HttpServletRequestWrapper</code></a> and <a href="http://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpServletResponseWrapper.html"><code>HttpServletResponseWrapper</code></a></li>
<li><a href="https://docs.oracle.com/javase/7/docs/api/javax/swing/JScrollPane.html"><code>javax.swing.JScrollPane</code></a></li>
</ul>
<h3 id="facade"><a href="http://en.wikipedia.org/wiki/Facade_pattern">Facade</a> (recognizeable by behavioral methods which internally uses instances of <em>different</em> independent abstract/interface types)</h3>
<ul>
<li><a href="http://docs.oracle.com/javaee/7/api/javax/faces/context/FacesContext.html"><code>javax.faces.context.FacesContext</code></a>, it internally uses among others the abstract/interface types <a href="http://docs.oracle.com/javaee/7/api/javax/faces/lifecycle/Lifecycle.html"><code>LifeCycle</code></a>, <a href="http://docs.oracle.com/javaee/7/api/javax/faces/application/ViewHandler.html"><code>ViewHandler</code></a>, <a href="http://docs.oracle.com/javaee/7/api/javax/faces/application/NavigationHandler.html"><code>NavigationHandler</code></a> and many more without that the enduser has to worry about it (which are however overrideable by injection).</li>
<li><a href="http://docs.oracle.com/javaee/7/api/javax/faces/context/ExternalContext.html"><code>javax.faces.context.ExternalContext</code></a>, which internally uses <a href="http://docs.oracle.com/javaee/7/api/javax/servlet/ServletContext.html"><code>ServletContext</code></a>, <a href="http://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpSession.html"><code>HttpSession</code></a>, <a href="http://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpServletRequest.html"><code>HttpServletRequest</code></a>, <a href="http://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpServletResponse.html"><code>HttpServletResponse</code></a>, etc.</li>
</ul>
<h3 id="flyweight"><a href="http://en.wikipedia.org/wiki/Flyweight_pattern">Flyweight</a> (recognizeable by creational methods returning a cached instance, a bit the &quot;multiton&quot; idea)</h3>
<ul>
<li><a href="http://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html#valueOf-int-"><code>java.lang.Integer#valueOf(int)</code></a> (also on <a href="http://docs.oracle.com/javase/8/docs/api/java/lang/Boolean.html#valueOf-boolean-"><code>Boolean</code></a>, <a href="http://docs.oracle.com/javase/8/docs/api/java/lang/Byte.html#valueOf-byte-"><code>Byte</code></a>, <a href="http://docs.oracle.com/javase/8/docs/api/java/lang/Character.html#valueOf-char-"><code>Character</code></a>, <a href="http://docs.oracle.com/javase/8/docs/api/java/lang/Short.html#valueOf-short-"><code>Short</code></a>, <a href="http://docs.oracle.com/javase/8/docs/api/java/lang/Long.html#valueOf-long-"><code>Long</code></a> and <a href="https://docs.oracle.com/javase/8/docs/api/java/math/BigDecimal.html#valueOf-long-int-"><code>BigDecimal</code></a>)</li>
</ul>
<h3 id="proxy"><a href="http://en.wikipedia.org/wiki/Proxy_pattern">Proxy</a> (recognizeable by creational methods which returns an implementation of given abstract/interface type which in turn <em>delegates/uses</em> a <em>different</em> implementation of given abstract/interface type)</h3>
<ul>
<li><a href="http://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Proxy.html"><code>java.lang.reflect.Proxy</code></a></li>
<li><a href="http://docs.oracle.com/javase/8/docs/api/java/rmi/package-summary.html"><code>java.rmi.*</code></a></li>
<li><a href="http://docs.oracle.com/javaee/7/api/javax/ejb/EJB.html"><code>javax.ejb.EJB</code></a> (<a href="https://stackoverflow.com/questions/25514361/when-using-ejb-does-each-managed-bean-get-its-own-ejb-instance">explanation here</a>)</li>
<li><a href="http://docs.oracle.com/javaee/7/api/javax/inject/Inject.html"><code>javax.inject.Inject</code></a> (<a href="https://stackoverflow.com/questions/29651008/field-getobj-returns-all-nulls-on-injected-cdi-managed-beans-while-manually-i/29672591#29672591">explanation here</a>)</li>
<li><a href="http://docs.oracle.com/javaee/7/api/javax/persistence/PersistenceContext.html"><code>javax.persistence.PersistenceContext</code></a></li>
</ul>
<h2 id="behavioral-patterns"><a href="http://en.wikipedia.org/wiki/Behavioral_pattern">Behavioral patterns</a></h2>
<h3 id="chain-of-responsibility"><a href="http://en.wikipedia.org/wiki/Chain_of_responsibility_pattern">Chain of responsibility</a> (recognizeable by behavioral methods which (indirectly) invokes the same method in <em>another</em> implementation of <em>same</em> abstract/interface type in a queue)</h3>
<ul>
<li><a href="http://docs.oracle.com/javase/8/docs/api/java/util/logging/Logger.html#log-java.util.logging.Level-java.lang.String-"><code>java.util.logging.Logger#log()</code></a></li>
<li><a href="http://docs.oracle.com/javaee/7/api/javax/servlet/Filter.html#doFilter-javax.servlet.ServletRequest-javax.servlet.ServletResponse-javax.servlet.FilterChain-"><code>javax.servlet.Filter#doFilter()</code></a></li>
</ul>
<h3 id="command"><a href="http://en.wikipedia.org/wiki/Command_pattern">Command</a> (recognizeable by behavioral methods in an abstract/interface type which invokes a method in an implementation of a <em>different</em> abstract/interface type which has been <em>encapsulated</em> by the command implementation during its creation)</h3>
<ul>
<li>All implementations of <a href="http://docs.oracle.com/javase/8/docs/api/java/lang/Runnable.html"><code>java.lang.Runnable</code></a></li>
<li>All implementations of <a href="http://docs.oracle.com/javase/8/docs/api/javax/swing/Action.html"><code>javax.swing.Action</code></a></li>
</ul>
<h3 id="interpreter"><a href="http://en.wikipedia.org/wiki/Interpreter_pattern">Interpreter</a> (recognizeable by behavioral methods returning a <em>structurally</em> different instance/type of the given instance/type; note that parsing/formatting is not part of the pattern, determining the pattern and how to apply it is)</h3>
<ul>
<li><a href="http://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html"><code>java.util.Pattern</code></a></li>
<li><a href="http://docs.oracle.com/javase/8/docs/api/java/text/Normalizer.html"><code>java.text.Normalizer</code></a></li>
<li>All subclasses of <a href="http://docs.oracle.com/javase/8/docs/api/java/text/Format.html"><code>java.text.Format</code></a></li>
<li>All subclasses of <a href="http://docs.oracle.com/javaee/7/api/javax/el/ELResolver.html"><code>javax.el.ELResolver</code></a></li>
</ul>
<h3 id="iterator"><a href="http://en.wikipedia.org/wiki/Iterator_pattern">Iterator</a> (recognizeable by behavioral methods sequentially returning instances of a <em>different</em> type from a queue)</h3>
<ul>
<li>All implementations of <a href="http://docs.oracle.com/javase/8/docs/api/java/util/Iterator.html"><code>java.util.Iterator</code></a> (thus among others also <a href="http://docs.oracle.com/javase/8/docs/api/java/util/Scanner.html"><code>java.util.Scanner</code></a>!).</li>
<li>All implementations of <a href="http://docs.oracle.com/javase/8/docs/api/java/util/Enumeration.html"><code>java.util.Enumeration</code></a></li>
</ul>
<h3 id="mediator"><a href="http://en.wikipedia.org/wiki/Mediator_pattern">Mediator</a> (recognizeable by behavioral methods taking an instance of different abstract/interface type (usually using the command pattern) which delegates/uses the given instance)</h3>
<ul>
<li><a href="http://docs.oracle.com/javase/8/docs/api/java/util/Timer.html"><code>java.util.Timer</code></a> (all <code>scheduleXXX()</code> methods)</li>
<li><a href="http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executor.html#execute-java.lang.Runnable-"><code>java.util.concurrent.Executor#execute()</code></a></li>
<li><a href="http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html"><code>java.util.concurrent.ExecutorService</code></a> (the <code>invokeXXX()</code> and <code>submit()</code> methods)</li>
<li><a href="http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ScheduledExecutorService.html"><code>java.util.concurrent.ScheduledExecutorService</code></a> (all <code>scheduleXXX()</code> methods)</li>
<li><a href="http://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Method.html#invoke-java.lang.Object-java.lang.Object...-"><code>java.lang.reflect.Method#invoke()</code></a></li>
</ul>
<h3 id="memento"><a href="http://en.wikipedia.org/wiki/Memento_pattern">Memento</a> (recognizeable by behavioral methods which internally changes the state of the <em>whole</em> instance)</h3>
<ul>
<li><a href="http://docs.oracle.com/javase/8/docs/api/java/util/Date.html"><code>java.util.Date</code></a> (the setter methods do that, <code>Date</code> is internally represented by a <code>long</code> value)</li>
<li>All implementations of <a href="http://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html"><code>java.io.Serializable</code></a></li>
<li>All implementations of <a href="http://docs.oracle.com/javaee/7/api/javax/faces/component/StateHolder.html"><code>javax.faces.component.StateHolder</code></a></li>
</ul>
<h3 id="observer-or-publishsubscribe"><a href="http://en.wikipedia.org/wiki/Observer_pattern">Observer (or Publish/Subscribe)</a> (recognizeable by behavioral methods which invokes a method on an instance of <em>another</em> abstract/interface type, depending on own state)</h3>
<ul>
<li><a href="http://docs.oracle.com/javase/8/docs/api/java/util/Observer.html"><code>java.util.Observer</code></a>/<a href="http://docs.oracle.com/javase/8/docs/api/java/util/Observable.html"><code>java.util.Observable</code></a> (rarely used in real world though)</li>
<li>All implementations of <a href="http://docs.oracle.com/javase/8/docs/api/java/util/EventListener.html"><code>java.util.EventListener</code></a> (practically all over Swing thus)</li>
<li><a href="http://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpSessionBindingListener.html"><code>javax.servlet.http.HttpSessionBindingListener</code></a></li>
<li><a href="http://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpSessionAttributeListener.html"><code>javax.servlet.http.HttpSessionAttributeListener</code></a></li>
<li><a href="http://docs.oracle.com/javaee/7/api/javax/faces/event/PhaseListener.html"><code>javax.faces.event.PhaseListener</code></a></li>
</ul>
<h3 id="state"><a href="http://en.wikipedia.org/wiki/State_pattern">State</a> (recognizeable by behavioral methods which changes its behaviour depending on the instance's state which can be controlled externally)</h3>
<ul>
<li><a href="http://docs.oracle.com/javaee/7/api/javax/faces/lifecycle/Lifecycle.html#execute-javax.faces.context.FacesContext-"><code>javax.faces.lifecycle.LifeCycle#execute()</code></a> (controlled by <a href="http://docs.oracle.com/javaee/7/api/javax/faces/webapp/FacesServlet.html"><code>FacesServlet</code></a>, the behaviour is dependent on current phase (state) of JSF lifecycle)</li>
</ul>
<h3 id="strategy"><a href="http://en.wikipedia.org/wiki/Strategy_pattern">Strategy</a> (recognizeable by behavioral methods in an abstract/interface type which invokes a method in an implementation of a <em>different</em> abstract/interface type which has been <em>passed-in</em> as method argument into the strategy implementation)</h3>
<ul>
<li><a href="http://docs.oracle.com/javase/8/docs/api/java/util/Comparator.html#compare-T-T-"><code>java.util.Comparator#compare()</code></a>, executed by among others <code>Collections#sort()</code>.</li>
<li><a href="http://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpServlet.html"><code>javax.servlet.http.HttpServlet</code></a>, the <code>service()</code> and all <code>doXXX()</code> methods take <code>HttpServletRequest</code> and <code>HttpServletResponse</code> and the implementor has to process them (and not to get hold of them as instance variables!).</li>
<li><a href="http://docs.oracle.com/javaee/7/api/javax/servlet/Filter.html#doFilter-javax.servlet.ServletRequest-javax.servlet.ServletResponse-javax.servlet.FilterChain-"><code>javax.servlet.Filter#doFilter()</code></a></li>
</ul>
<h3 id="template-method"><a href="http://en.wikipedia.org/wiki/Template_method_pattern">Template method</a> (recognizeable by behavioral methods which already have a &quot;default&quot; behaviour defined by an abstract type)</h3>
<ul>
<li>All non-abstract methods of <a href="http://docs.oracle.com/javase/8/docs/api/java/io/InputStream.html"><code>java.io.InputStream</code></a>, <a href="http://docs.oracle.com/javase/8/docs/api/java/io/OutputStream.html"><code>java.io.OutputStream</code></a>, <a href="http://docs.oracle.com/javase/8/docs/api/java/io/Reader.html"><code>java.io.Reader</code></a> and <a href="http://docs.oracle.com/javase/8/docs/api/java/io/Writer.html"><code>java.io.Writer</code></a>.</li>
<li>All non-abstract methods of <a href="http://docs.oracle.com/javase/8/docs/api/java/util/AbstractList.html"><code>java.util.AbstractList</code></a>, <a href="http://docs.oracle.com/javase/8/docs/api/java/util/AbstractSet.html"><code>java.util.AbstractSet</code></a> and <a href="http://docs.oracle.com/javase/8/docs/api/java/util/AbstractMap.html"><code>java.util.AbstractMap</code></a>.</li>
<li><a href="http://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpServlet.html"><code>javax.servlet.http.HttpServlet</code></a>, all the <code>doXXX()</code> methods by default sends a HTTP 405 &quot;Method Not Allowed&quot; error to the response. You're free to implement none or any of them.</li>
</ul>
<h3 id="visitor"><a href="http://en.wikipedia.org/wiki/Visitor_pattern">Visitor</a> (recognizeable by two <em>different</em> abstract/interface types which has methods defined which takes each the <em>other</em> abstract/interface type; the one actually calls the method of the other and the other executes the desired strategy on it)</h3>
<ul>
<li><a href="http://docs.oracle.com/javase/8/docs/api/javax/lang/model/element/AnnotationValue.html"><code>javax.lang.model.element.AnnotationValue</code></a> and <a href="http://docs.oracle.com/javase/8/docs/api/javax/lang/model/element/AnnotationValueVisitor.html"><code>AnnotationValueVisitor</code></a></li>
<li><a href="http://docs.oracle.com/javase/8/docs/api/javax/lang/model/element/Element.html"><code>javax.lang.model.element.Element</code></a> and <a href="http://docs.oracle.com/javase/8/docs/api/javax/lang/model/element/ElementVisitor.html"><code>ElementVisitor</code></a></li>
<li><a href="http://docs.oracle.com/javase/8/docs/api/javax/lang/model/type/TypeMirror.html"><code>javax.lang.model.type.TypeMirror</code></a> and <a href="http://docs.oracle.com/javase/8/docs/api/javax/lang/model/type/TypeVisitor.html"><code>TypeVisitor</code></a></li>
<li><a href="http://docs.oracle.com/javase/8/docs/api/java/nio/file/FileVisitor.html"><code>java.nio.file.FileVisitor</code></a> and <a href="http://docs.oracle.com/javase/8/docs/api/java/nio/file/SimpleFileVisitor.html"><code>SimpleFileVisitor</code></a></li>
<li><a href="http://docs.oracle.com/javaee/7/api/javax/faces/component/visit/VisitContext.html"><code>javax.faces.component.visit.VisitContext</code></a> and <a href="http://docs.oracle.com/javaee/7/api/javax/faces/component/visit/VisitCallback.html"><code>VisitCallback</code></a></li>
</ul>
<hr>
<p>译文：</p>
<h4 id="创作模式"><strong>创作模式</strong></h4>
<p><strong>抽象工厂模式</strong> （通过创造性的方法来识别工厂本身，这又可以用于创建另一个抽象 / 接口类型）</p>
<ul>
<li>javax.xml.parsers.DocumentBuilderFactory#newInstance()</li>
<li>javax.xml.transform.TransformerFactory#newInstance()</li>
<li>javax.xml.xpath.XPathFactory#newInstance()</li>
</ul>
<p><strong>建造者模式</strong> （通过创建方法识别返回实例本身）</p>
<ul>
<li>java.lang.StringBuilder#append() （非线程安全）</li>
<li>java.lang.StringBuffer#append() （线程安全）</li>
<li>java.nio.ByteBuffer#put()（还 CharBuffer，ShortBuffer，IntBuffer，LongBuffer</li>
<li>FloatBuffer 和 DoubleBuffer）</li>
<li>javax.swing.GroupLayout.Group#addComponent()</li>
<li>所有的实现 java.lang.Appendable</li>
</ul>
<p><strong>工厂模式</strong> （可通过创建方法识别返回抽象 / 接口类型的实现）</p>
<ul>
<li>java.util.Calendar#getInstance()</li>
<li>java.util.ResourceBundle#getBundle()</li>
<li>java.text.NumberFormat#getInstance()</li>
<li>java.nio.charset.Charset#forName()</li>
<li>java.net.URLStreamHandlerFactory#createURLStreamHandler(String) （每个协议返回单例对象）</li>
<li>java.util.EnumSet#of()</li>
<li>javax.xml.bind.JAXBContext#createMarshaller() 和其他类似的方法</li>
</ul>
<p><strong>原型模式</strong> （通过创建方法识别，返回具有相同属性的其他实例）</p>
<ul>
<li>java.lang.Object#clone()（班必须实施 java.lang.Cloneable）</li>
</ul>
<p><strong>单例模式</strong>（通过创造性方法识别，每次返回相同的实例（通常是自己））</p>
<ul>
<li>java.lang.Runtime#getRuntime()</li>
<li>java.awt.Desktop#getDesktop()</li>
<li>java.lang.System#getSecurityManager()</li>
</ul>
<h4 id="结构模式"><strong>结构模式</strong></h4>
<p><strong>适配器模式</strong> （可通过创建方法识别采用不同抽象 / 接口类型的实例，并返回自己 / 另一个抽象 / 接口类型的实现，其装饰 / 覆盖给定实例）</p>
<ul>
<li>java.util.Arrays#asList()</li>
<li>java.util.Collections#list()</li>
<li>java.util.Collections#enumeration()java.io.InputStreamReader(InputStream)（返回 a Reader）</li>
<li>java.io.OutputStreamWriter(OutputStream)（返回 a Writer）</li>
<li>javax.xml.bind.annotation.adapters.XmlAdapter#marshal() 和 #unmarshal()</li>
</ul>
<p><strong>桥接模式</strong> （可以通过创建方法识别采用不同抽象 / 接口类型的实例，并返回自己的使用给定实例的抽象 / 接口类型的实现）</p>
<p>一个虚构的例子将会 new LinkedHashMap(LinkedHashSet&lt; K&gt;, List&lt; V&gt;) 返回一个不可修改的链接映射，它不会克隆，而是使用它们。该 java.util.Collections#newSetFromMap() 和 singletonXXX() 方法却接近。</p>
<p><strong>组合模式</strong> （通过将具有相同抽象 / 接口类型的实例的行为方法识别为树结构）</p>
<ul>
<li>java.awt.Container#add(Component) （几乎全部摆动）</li>
<li>javax.faces.component.UIComponent#getChildren()</li>
</ul>
<p><strong>装饰器模式</strong> （通过创作方法识别采用相同抽象 / 接口类型的实例，添加额外的行为）</p>
<ul>
<li>所有子类 java.io.InputStream，OutputStream，Reader 并 Writer 有一个构造函数取相同类型的实例。</li>
<li>java.util.Collections 的 checkedXXX()，synchronizedXXX() 和 unmodifiableXXX() 方法。</li>
<li>javax.servlet.http.HttpServletRequestWrapper 和 HttpServletResponseWrapper</li>
</ul>
<p><strong>门面模式</strong> （可通过内部使用不同独立抽象 / 接口类型实例的行为方法识别）</p>
<ul>
<li>javax.faces.context.FacesContext，它在内部等使用抽象 / 接口类型 LifeCycle，ViewHandler，NavigationHandler 等等而没有终端用户具有担心它（它们然而通过注射覆写投放）。</li>
<li>javax.faces.context.ExternalContext，其在内部使用 ServletContext，HttpSession，HttpServletRequest，HttpServletResponse，等。</li>
</ul>
<p><strong>享元模式</strong> （使用缓存来加速大量小对象的访问时间）</p>
<ul>
<li>java.lang.Integer#valueOf(int)（还 Boolean，Byte，Character，Short，Long 和 BigDecimal）</li>
</ul>
<p><strong>代理模式</strong> （可通过创建方法识别，该方法返回给定的抽象 / 接口类型的实现，该类型依次代表 / 使用给定抽象 / 接口类型的不同实现）</p>
<ul>
<li>java.lang.reflect.Proxy</li>
<li>java.rmi.*</li>
<li>javax.ejb.EJB</li>
<li>javax.inject.Inject</li>
<li>javax.persistence.PersistenceContext</li>
</ul>
<h4 id="行为模式"><strong>行为模式</strong></h4>
<p><strong>责任链模式</strong> （通过行为方法识别（间接地）在队列中的相同抽象 / 接口类型的另一个实现中调用相同的方法）</p>
<ul>
<li>java.util.logging.Logger#log()</li>
<li>javax.servlet.Filter#doFilter()</li>
</ul>
<p><strong>命令模式</strong> （可以通过抽象 / 接口类型中的行为方法识别，该方法在创建时由命令实现封装的不同抽象 / 接口类型的实现中调用方法）</p>
<ul>
<li>所有的实现 java.lang.Runnable</li>
<li>所有的实现 javax.swing.Action</li>
</ul>
<p><strong>解释器模式</strong> （通过行为方法识别，返回结构不同的实例 / 给定实例 / 类型的类型; 请注意，解析 / 格式化不是模式的一部分，确定模式以及如何应用它）</p>
<ul>
<li>java.util.Pattern</li>
<li>java.text.Normalizer</li>
<li>所有子类 java.text.Format</li>
<li>所有子类 javax.el.ELResolver</li>
</ul>
<p><strong>迭代器模式</strong> （可通过行为方法识别，从队列中顺序返回不同类型的实例）</p>
<ul>
<li>所有的实现 java.util.Iterator（因此还有 java.util.Scanner！）。</li>
<li>所有的实现 java.util.Enumeration</li>
</ul>
<p><strong>中介者模式</strong> （通过采用不同的抽象 / 接口类型（通常使用命令模式）实例的行为方法来识别给定实例）</p>
<ul>
<li>java.util.Timer（所有 scheduleXXX() 方法）</li>
<li>java.util.concurrent.Executor#execute()</li>
<li>java.util.concurrent.ExecutorService（invokeXXX() 和 submit() 方法）</li>
<li>java.util.concurrent.ScheduledExecutorService（所有 scheduleXXX() 方法）</li>
<li>java.lang.reflect.Method#invoke()</li>
</ul>
<p><strong>备忘录模式</strong> （可以通过内部改变整个实例的状态的行为方法来识别）</p>
<ul>
<li>java.util.Date（setter 方法这样做，Date 内部由一个 long 值表示）</li>
<li>所有的实现 java.io.Serializable</li>
<li>所有的实现 javax.faces.component.StateHolder</li>
</ul>
<p><strong>观察者模式</strong>（或发布 / 订阅） （可以通过行为方法识别，根据自己的状态调用另一个抽象 / 接口类型的实例上的方法）</p>
<ul>
<li>java.util.Observer/ java.util.Observable（很少在现实世界中使用）</li>
<li>所有实现 java.util.EventListener（因此实际上各地的 Swing）</li>
<li>javax.servlet.http.HttpSessionBindingListener</li>
<li>javax.servlet.http.HttpSessionAttributeListener</li>
<li>javax.faces.event.PhaseListener</li>
</ul>
<p><strong>状态模式</strong> （可以通过行为方法识别，根据可以从外部控制的实例的状态改变其行为）</p>
<ul>
<li>javax.faces.lifecycle.LifeCycle#execute()（FacesServlet 由此控制，行为取决于 JSF 生命周期的当前阶段（状态））</li>
</ul>
<p><strong>策略</strong> （可以通过抽象 / 接口类型中的行为方法识别，该方法在已经作为方法参数传递到策略实现中的不同抽象 / 接口类型的实现中调用方法）</p>
<ul>
<li>java.util.Comparator#compare()，由其他人执行 Collections#sort()。</li>
<li>javax.servlet.http.HttpServlet，service() 所有的 doXXX() 方法 HttpServletRequest</li>
<li>HttpServletResponse 实现者必须处理它们（而不是把它们保持为实例变量！）。</li>
<li>javax.servlet.Filter#doFilter()</li>
</ul>
<p><strong>模板方法</strong> （可以由已经具有抽象类型定义的 “默认” 行为的行为方法识别）</p>
<ul>
<li>所有非抽象方法 java.io.InputStream，java.io.OutputStream，java.io.Reader 和 java.io.Writer。</li>
<li>所有非抽象方法 java.util.AbstractList，java.util.AbstractSet 和 java.util.AbstractMap。</li>
<li>javax.servlet.http.HttpServlet，doXXX() 默认情况下，所有方法都会向响应发送 HTTP 405“方法不允许” 错误。你可以自由地执行任何一个或任何它们。</li>
</ul>
<p><strong>访问者</strong> （可以通过两种不同的抽象 / 接口类型识别，它们的方法定义为采用每个其他抽象 / 接口类型; 实际上调用另一个抽象 / 接口类型的方法，另一个执行所需的策略）</p>
<ul>
<li>javax.lang.model.element.AnnotationValue 和 AnnotationValueVisitor</li>
<li>javax.lang.model.element.Element 和 ElementVisitor</li>
<li>javax.lang.model.type.TypeMirror 和 TypeVisitor</li>
<li>java.nio.file.FileVisitor 和 SimpleFileVisitor</li>
<li>javax.faces.component.visit.VisitContext and VisitCallback</li>
</ul>

        </div>
        <!-- Share to Twitter, Weibo, Telegram -->
        <div class="flex items-center">
          <div class="mr-4 flex items-center">
            <i class="ri-share-forward-line text-gray-500"></i>
          </div>
          <div class="px-4 cursor-pointer text-blue-500 hover:bg-blue-100 dark:hover:bg-gray-600 inline-flex" @click="shareToTwitter">
            <i class="ri-twitter-line"></i>
          </div>
          <div class="px-4 cursor-pointer text-red-500 hover:bg-red-100 dark:hover:bg-gray-600 inline-flex" @click="shareToWeibo">
            <i class="ri-weibo-line"></i>
          </div>
          <div class="px-4 cursor-pointer text-indigo-500 hover:bg-indigo-100 dark:hover:bg-gray-600 inline-flex" @click="shareToTelegram">
            <i class="ri-telegram-line"></i>
          </div>
        </div>
      </div>

      
        
          <div id="gitalk-container"></div>
        

        
      

      
        <div id="vlaine-comment"></div>
      

      <footer class="py-12 text-center px-4 md:px-0" v-pre>
  Powered by <a href="https://github.com/getgridea/gridea" target="_blank">Gridea</a>  Made by  <a href="https://github.com/JoyZgq" target="_blank">zgq</a> 🎈❤❤❤🌹
</footer>
    </div>

    <!-- TOC Container -->
    <div class="fixed right-0 bottom-0 mb-16 mr-4 shadow w-8 h-8 rounded-full flex justify-center items-center z-10 cursor-pointer bg-white dark:bg-gray-500 dark:text-gray-200 hover:shadow-lg transition-all animated fadeInRight" @click="showToc = true">
      <i class="ri-file-list-line"></i>
    </div>

    <div class="fixed right-0 top-0 bottom-0 overflow-y-auto w-64 bg-white dark:bg-gray-800 p-4 border-l border-gray-100 dark:border-gray-600 z-10 transition-fast" :class="{ '-mr-64': !showToc }">
      <div class="flex mb-4 justify-end">
        <div class="w-8 h-8 inline-flex justify-center items-center rounded-full cursor-pointer hover:bg-gray-200 dark:hover:bg-gray-600 transition-fast" @click="showToc = false">
          <i class="ri-close-line text-lg"></i>
        </div>
      </div>
      <div class="post-toc-container">
        <ul class="markdownIt-TOC">
<li>
<ul>
<li><a href="#creational-patterns">Creational patterns</a>
<ul>
<li><a href="#abstract-factory">Abstract factory</a></li>
<li><a href="#builder">Builder</a></li>
<li><a href="#factory-method">Factory method</a></li>
<li><a href="#prototype">Prototype</a></li>
<li><a href="#singleton">Singleton</a></li>
</ul>
</li>
<li><a href="#structural-patterns">Structural patterns</a>
<ul>
<li><a href="#adapter">Adapter</a></li>
<li><a href="#bridge">Bridge</a></li>
<li><a href="#composite">Composite</a></li>
<li><a href="#decorator">Decorator</a></li>
<li><a href="#facade">Facade</a></li>
<li><a href="#flyweight">Flyweight</a></li>
<li><a href="#proxy">Proxy</a></li>
</ul>
</li>
<li><a href="#behavioral-patterns">Behavioral patterns</a>
<ul>
<li><a href="#chain-of-responsibility">Chain of responsibility</a></li>
<li><a href="#command">Command</a></li>
<li><a href="#interpreter">Interpreter</a></li>
<li><a href="#iterator">Iterator</a></li>
<li><a href="#mediator">Mediator</a></li>
<li><a href="#memento">Memento</a></li>
<li><a href="#observer-or-publishsubscribe">Observer (or Publish/Subscribe)</a></li>
<li><a href="#state">State</a></li>
<li><a href="#strategy">Strategy</a></li>
<li><a href="#template-method">Template method</a></li>
<li><a href="#visitor">Visitor</a>
<ul>
<li><a href="#%E5%88%9B%E4%BD%9C%E6%A8%A1%E5%BC%8F"><strong>创作模式</strong></a></li>
<li><a href="#%E7%BB%93%E6%9E%84%E6%A8%A1%E5%BC%8F"><strong>结构模式</strong></a></li>
<li><a href="#%E8%A1%8C%E4%B8%BA%E6%A8%A1%E5%BC%8F"><strong>行为模式</strong></a></li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>

      </div>
    </div>

    <!-- Back to top -->
    <div class="fixed right-0 bottom-0 mb-4 mr-4 shadow w-8 h-8 rounded-full flex justify-center items-center z-10 cursor-pointer bg-white hover:shadow-lg transition-all dark:bg-gray-500 dark:text-gray-200" @click="backToUp" v-show="scrolled">
      <i class="ri-arrow-up-line"></i>
    </div>
  </div>

  <!-- Root element of PhotoSwipe. Must have class pswp. -->
<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true">
  <!-- Background of PhotoSwipe. 
        It's a separate element as animating opacity is faster than rgba(). -->
  <div class="pswp__bg">
  </div>
  <!-- Slides wrapper with overflow:hidden. -->
  <div class="pswp__scroll-wrap">
    <!-- Container that holds slides. 
            PhotoSwipe keeps only 3 of them in the DOM to save memory.
            Don't modify these 3 pswp__item elements, data is added later on. -->
    <div class="pswp__container">
      <div class="pswp__item">
      </div>
      <div class="pswp__item">
      </div>
      <div class="pswp__item">
      </div>
    </div>
    <!-- Default (PhotoSwipeUI_Default) interface on top of sliding area. Can be changed. -->
    <div class="pswp__ui pswp__ui--hidden">
      <div class="pswp__top-bar">
        <!--  Controls are self-explanatory. Order can be changed. -->
        <div class="pswp__counter">
        </div>
        <button class="pswp__button pswp__button--close" title="Close (Esc)"></button>
        <button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button>
        <button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button>
        <!-- Preloader demo http://codepen.io/dimsemenov/pen/yyBWoR -->
        <!-- element will get class pswp__preloader--active when preloader is running -->
        <div class="pswp__preloader">
          <div class="pswp__preloader__icn">
            <div class="pswp__preloader__cut">
              <div class="pswp__preloader__donut">
              </div>
            </div>
          </div>
        </div>
      </div>
      <div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap">
        <div class="pswp__share-tooltip">
        </div>
      </div>
      <button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)">
      </button>
      <button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)">
      </button>
      <div class="pswp__caption">
        <div class="pswp__caption__center">
        </div>
      </div>
    </div>
  </div>
</div>

  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script src="https://JoyZgq.github.io/media/scripts/main.js"></script>
  
  <!-- Code Highlight -->
  
    <script src="https://JoyZgq.github.io/media/prism.js"></script>
    <script>
      Prism.highlightAll()
    </script>
  

  <script src="https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/photoswipe.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/photoswipe-ui-default.min.js"></script>
  <script>
    //拿到预览框架，也就是上面的html代码
    var pswpElement = document.querySelectorAll('.pswp')[0];
    //定义图片数组变量
    var imgitems;
    /**
    * 用于显示预览界面
    * @param index 图片数组下标
    */
    function viewImg(index) {
      //其它选项这里不做过多阐述，详情见官网
      var pswpoptions = {
        index: parseInt(index, 10), // 开始幻灯片索引。0是第一张幻灯片。必须是整数，而不是字符串。
        bgOpacity: 0.7, // 背景透明度，0-1
        maxSpreadZoom: 3, // 缩放级别，不要太大
      };
      //初始化并打开PhotoSwipe，pswpElement对应上面预览框架，PhotoSwipeUI_Default为皮肤，imgitems为图片数组，pswpoptions为选项
      var gallery = new PhotoSwipe(pswpElement, PhotoSwipeUI_Default, imgitems, pswpoptions);
      gallery.init()
    }
    /**
    * 用于添加图片点击事件
    * @param img 图片元素
    * @param index 所属下标（在imgitems中的位置）
    */
    function addImgClick(img, index) {
      img.onclick = function() {
        viewImg(index)
      }
    }
    /**
    * 轮询所有图片，获取src、width、height等数据，加入imgitems，并给图片元素添加事件
    * 最好在onload中执行该方法，本站因放在最底部，所以直接初始化
    * 异步加载图片可在图片元素创建完成后调用此方法
    */
    function initImg() {
      //重置图片数组
      imgitems = [];
      //查找class:markdown 下的所有img元素并遍历
      var imgs = document.querySelectorAll('.markdown img');
      for (var i = 0; i < imgs.length; i++) {
        var img = imgs[i];
        //本站相册初始为loading图片，真实图片放在data-src
        var ds = img.getAttribute("data-src");
        //创建image对象，用于获取图片宽高
        var imgtemp = new Image();
        //判断是否存在data-src
        if (ds != null && ds.length > 0) {
          imgtemp.src = ds
        } else {
          imgtemp.src = img.src
        }
        //判断是否存在缓存
        if (imgtemp.complete) {
          var imgobj = {
            "src": imgtemp.src,
            "w": imgtemp.width,
            "h": imgtemp.height,
          };
          imgitems[i] = imgobj;
          addImgClick(img, i);
        } else {
          console.log('进来了2')
          imgtemp.index = i;
          imgtemp.img = img;
          imgtemp.onload = function() {
            var imgobj = {
              "src": this.src,
              "w": this.width,
              "h": this.height,
            };
            //不要使用push，因为onload前后顺序会不同
            imgitems[this.index] = imgobj
            //添加点击事件
            addImgClick(this.img, this.index);
          }
        }
      }
    }
    //初始化
    initImg();
  </script>
  
    <script type="application/javascript" src="https://unpkg.com/valine"></script>
<script type="application/javascript">
  new Valine({
    el: '#vlaine-comment',
    appId: 'Sy2gsMvGcPQl3gTGsqqYsHW6-gzGzoHsz',
    appKey: 'IpsgegiMUNgRg7l5BVXk6EXM',
    pageSize: 10,
    notify: false,
    avatar: 'mp',
    verify: true,
    placeholder: '客官来都来了，不妨评论一下🌹🐱‍👤',
    visitor: true,
    highlight: false,
    recordIP: true,
  })
</script>
  
  
    
      <link rel="stylesheet" href="https://unpkg.com/gitalk/dist/gitalk.css">
<script type="application/javascript" src="https://unpkg.com/gitalk/dist/gitalk.min.js"></script>

<script type="application/javascript">

  var gitalk = new Gitalk({
    clientID: '83da62f594c23db993f3',
    clientSecret: '9aa795ad06ecb4133721f1acf047ecb1e4f295e8',
    repo: 'GitalkApp',
    owner: 'JoyZgq',
    admin: ['JoyZgq'],
    id: (location.pathname).substring(0, 49),      // Ensure uniqueness and length less than 50
    distractionFreeMode: false  // Facebook-like distraction free mode
  })

  gitalk.render('gitalk-container')

</script>

    
  
</body>

</html>